package com.tutu.aop.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;

import java.sql.SQLOutput;

/**
 * @Program: SpringBoot
 * @Description: 自定义切面类
 * @Author: JK.TuTu
 * @Create: 2022-11-04 10:49
 **/
@Aspect //表示当前类是切面类
@Configuration
public class MyAspectConfig {
    /**
     * 前置通知方法 在目标方法执行前执行
     *
     * @param jp 连接点 里包含了类名、被切面的方法名，参数等属性
     */
    @Before("execution(public void com.tutu.aop.service.impl.UserServiceImpl.deleteUser((String)))")
    public void beforeMethod(JoinPoint jp) {
        System.out.println("前置通过方法==========");
        System.out.println("执行业务方法的名称" + jp.getSignature().getName());
        Object[] args = jp.getArgs();
        for (Object arg : args) {
            System.out.println("业务方法的参数:" + arg);
        }
    }

    /**
     * 后置通知方法 在目标方法执行后执行
     */
    @After("execution(public void com.tutu.aop.service.impl.UserServiceImpl.updateUser((com.tutu.aop.entity.User)))")
    public void afterMethod(JoinPoint jp) {
        System.out.println("执行业务方法的名称:" + jp.getSignature().getName());
        System.out.println("后置通知方法==========");
    }

    /**
     * 返回通知，在方法返回结果之后执行
     * returning:自定义的变量名，表示目标方法返回值，必须和通知方法的形参名一致
     *
     * @param data 是目标方法执行后的返回值，根据返回值做切面的功能处理
     */
    @AfterReturning(value = "execution(public String com.tutu.aop.service.impl.UserServiceImpl.getUser((int)))", returning = "data")
    public void afterReturningMethod(JoinPoint jp, Object data) {
        System.out.println("执行业务方法的名称:" + jp.getSignature().getName());
        System.out.println("后置通知方法的返回结果:" + data);
        System.out.println("返回通知方法==========");
    }

    /**
     * 环绕通知方法 在目标方法的前后都可以执行 方法必须有一个返回值
     *
     * @param jp
     * @throws Throwable
     */
    //@Around("execution(public String com.tutu.aop.service.impl.UserServiceImpl.getUserById(int,String))")
    @Around("@annotation(com.tutu.aop.annotation.MyAdvice)")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕通知前.....");
        //可根据目标方法的参数 判断是否执行目标方法
        //获取目标方法的所有参数
        Object[] args = jp.getArgs();
        int age = (int) args[0];
        String name = (String) args[1];
        if (age == 18 || name.equals("张三")) {
            // 获取目标方法的返回值
            Object data = jp.proceed();
            System.out.println("目标方法返回值:" + data);
        }
        System.out.println("环绕通知后.......");
    }


}
